본문으로 건너뛰기

Part 3: Personal Data Flow

ItemContent
Document NamePart 3: Personal Data Flow
Product NameDTA Wide Sleep Management Platform
Date2026-06-18
ScopePart 3 (Backend) — limited to user personal/sensitive data
Related ArticlesO.Purp_1/3/7, O.Data_1/2/3/5/6/7, O.Arch_2/5, O.TrdP_6/9/10, O.Ntwk_1
Reference StandardsBSI TR-03161, GDPR Art. 30 (Records of processing)

1. Purpose and Scope​

This document defines the collection, processing, storage, transfer, and deletion flow of user personal and sensitive data processed by the DTA Wide backend (dta-wide-api). It serves as shared evidence for several BSI articles (see §0 mapping).

Scope limitation: This document covers personal and sensitive data only. Non-personal operational data (configuration, lookup tables, logging infrastructure) and the overall application architecture are out of scope. For system architecture see p3_01_backend_infra_architecture, for cloud outsourcing responsibility see p3_04_cloud_outsourcing_responsibility, and for cryptographic key lifecycle see p3_05_cryptographic_key_lifecycle.

Every factual statement in this document is backed by a code/schema anchor (file:line).

0. BSI Articles Covered by This Document​

SectionCovered Articles
§2 Personal data inventory & classificationO.Purp_1 (BSIA-238), O.Data_3 (314), O.Arch_2 (246)
§3 Data flow diagramO.Arch_2 (246), O.Ntwk_1 (327)
§4 Lifecycle (collection→deletion)O.Purp_3 (240), O.Data_2 (313), O.Data_7 (318)
§5 Storage map + at-rest encryptionO.Data_1 (312), O.Arch_4 (248)
§6 External / third-party sharing matrixO.TrdP_6 (273), O.TrdP_9 (276), O.TrdP_10 (277), O.Purp_7 (244)
§7 Interface protection & notificationsO.Arch_5 (249), O.Data_5 (316), O.Data_6 (317)

2. Personal Data Inventory and Classification​

Categories of personal/sensitive data processed by the backend. Default storage is PostgreSQL (Cloud SQL, private schema).

CategoryData itemStorage (anchor)Classification
Identity — eIDeidHash (SHA-256, unique)eid_links.eid_hash (private.prisma:247)Pseudonymized
Identity — eIDkvnr (insurance number, persisted)eid_links.kvnr VarChar(10) (private.prisma:248)Sensitive
Identity — eIDmetadata (sub·email·name [·insurer])eid_links.metadata Json (private.prisma:249)Personal
Identity — eIDbirthdateNot stored / not used (DTO only)—
Authenticationrefresh/access token, app token, sessionRefreshToken/AccessToken/AppToken/Session (private.prisma:162/182/220/198)Secret
Authentication — 2FAdevice public key (ECC P-256 SPKI)user_device_authentications.public_key_spki (private.prisma)Public key
Consentconsent/revocation history, IP, integrity HMACuser_agreementments (private.prisma:307-329)Personal
Usage historyuserId, IP, User-Agent, timestampUsageHistory (private.prisma)Personal
Health datasleep logs / questionnaire responses (transformed)Firestore (agent-data repositories)Sensitive

eID attribute storage (correction reflected): eID profile attributes are not discarded transiently; they are stored in eid_links.metadata (Json). The stored fields differ by write path — initial signup (eu-signup-orchestrator.service.ts:270-273) stores sub·email·name, while link completion (complete-eid-link.handler.ts:104-110) additionally stores insurer. kvnr is persisted to prevent ePA re-authentication (schema comment, plan 177 agenda-001) and is masked on use (Kvnr.masked() — kvnr.vo.ts:28). birthdate exists in the DTO but is neither stored nor used (cohort is determined by access-code/OAuth state).


3. Data Flow Diagram​

Shows personal data collection → storage → (limited) external flow together with the trust boundary. The thick arrow (①) is inbound collection; the dotted arrow (④) is an inactive (no-transfer) path.

Flow summary: ① The app sends personal data over TLS; the API validates it (ValidationPipe) and ② stores it by category inside the trust boundary (GCP · EU, encrypted at rest — §5). The only personal/sensitive data flow that crosses the trust boundary is ③ the eID verification OAuth handshake with gematik, which carries no health data or KVNR. ④ The only external egress path for KVNR (ePA) is currently a stub, so no live transfer occurs (see §6). All inbound communication is TLS-encrypted (O.Ntwk_1, see p3_05/177-cryptography-justification).


4. Lifecycle (Collection → Processing → Storage → Transfer → Deletion)​

StageProcessingControl / anchor
CollectionInbound data validated by global ValidationPipe (whitelist:true); undeclared fields strippedmain.ts:641-667 (O.Source_1 / BSIA-257)
ProcessingPurpose-based minimization. Identifiers such as KVNR are masked before loggingkvnr.vo.ts:28, logger masking (177-data-purpose-mapping)
StoragePer-category stores (§5). Sensitive tokens and file URLs are field-encryptedauth.prisma:95, private.prisma:2082/2203
TransferExternal transfer limited to the §6 matrix. No live external transfer of health data or KVNR§6
DeletionOn account termination eID links are deleted (eidLink.deleteMany); 2FA device keys are cascade-deletedprivate.prisma (UserDeviceAuthentication onDelete: Cascade)

For retention/deletion policy detail see 177-data-retention-policy (O.Data_2/_7).


5. Storage Map and At-Rest Encryption​

StorePersonal data storedAt-rest encryption
PostgreSQL (Cloud SQL)identity (eID), authentication, consent, usage historyGCP default encryption at rest (platform) + application-level encryption for sensitive fields
Firestoretransformed sleep / questionnaire health dataGCP default encryption at rest (platform)
Redis (Memorystore)session / cache (short-lived)GCP default encryption at rest (platform)

Application-level field encryption (code-confirmed):

  • refresh_token_cipher — encrypted storage of external IdP refresh token (auth.prisma:95)
  • file_url_cipher — encrypted file URL (private.prisma:2203)
  • encryption_key_id — key identifier column (private.prisma:2082, a separate model from the above)

For platform encryption and key management detail see p3_05_cryptographic_key_lifecycle, 177-cryptography-justification.


6. External / Third-Party Sharing Matrix​

Complete set of paths by which the backend transfers personal data externally. (O.TrdP_6/9/10, O.Purp_7)

RecipientData transferredPurposeProtectionNote
gematik eID IdPOAuth authentication handshakeeID identity verificationTLS + OAuth/PKCENo health data transferred
ePA export(KVNR — not transferred)ePA integration (under development)—Only a stub adapter is bound — no live transfer (epa-export-stub.adapter.ts:16-25, binding feature-health-data-export.module.ts:103-104)
GCP sub-processorsdata stored per §5hosting · storage · messagingDPA + region pinning (EU)Cloud SQL/Firestore/Redis/Pub-Sub/BigQuery (p3_04)

O.TrdP_6 (no sensitive data transfer): Health data is not transferred to third parties other than GCP sub-processors (storage purpose, under DPA). The only external egress path for KVNR is ePA export; however, as of 2026-06-18 the ePA integration is under development, and the sole implementation bound in production is a stub adapter (EpaExportStubAdapter). On EpaExportPort.send the stub performs no actual transfer — it only emits a warning log and returns { accepted: true, referenceId: 'stub' }, and KVNR is not written to the log (epa-export-stub.adapter.ts:16-25). The domain handler's epaPort.send(...) call (epa-export.handler.ts:158) resolves to this stub via DI binding (feature-health-data-export.module.ts:103-104); thus the call site alone may read as a live transfer, but no live transfer occurs. A live adapter will replace the stub once the TIC/Konnektor infrastructure is ready. O.TrdP_9 (notification of external services): GCP sub-processors and data-sharing details are disclosed in the cloud outsourcing document (p3_04) and the privacy policy (the user-facing disclosure screen is in P.1-Mobile/landing scope).


7. Interface Protection and Notifications​

  • Interface protection (O.Arch_5 / O.TrdP_10): All interfaces to external services apply TLS encryption + authentication/authorization (scope) + input validation. Inbound validation follows §4 (collection); transport encryption follows O.Ntwk_1 (p3_05/177-cryptography-justification).
  • Data export control (O.Data_5): Export of KVNR/health data outside its source is limited to the §6 matrix; no other export path exists.
  • Notification payload (O.Data_6): Identifiers (e.g. KVNR) are masked on use (Kvnr.masked() — kvnr.vo.ts:28). Exclusion of sensitive data from notification/push payloads is managed separately as an O.Data_6 control item.

Appendix: Supporting Code Anchors​

FactAnchor
eID attributes stored in metadatacomplete-eid-link.handler.ts:104-110
eID link model / KVNR persistenceprivate.prisma:244-263
consent/revocation history + integrity HMACprivate.prisma:307-329
KVNR maskingkvnr.vo.ts:28
ePA egress = stub (no live transfer)epa-export-stub.adapter.ts:16-25 + binding feature-health-data-export.module.ts:103-104 (call site epa-export.handler.ts:158)
inbound validation (ValidationPipe)main.ts:641-667
field encryption — refresh tokenauth.prisma:95 (refresh_token_cipher)
field encryption — file URLprivate.prisma:2203 (file_url_cipher), key id private.prisma:2082 (encryption_key_id, separate model)